/*
 * $Id: $
 */
package org.rcgwt.client.ui.grid.internal;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import org.rcgwt.client.ui.grid.internal.model.IGridModel;
import org.rcgwt.client.ui.grid.internal.model.IRowModel;
import org.rcgwt.client.ui.grid.internal.model.IViewModel;
import org.rcgwt.client.ui.grid.internal.model.IViewModelElements;
import org.rcgwt.client.ui.grid.provider.IColumnProvider;
import org.rcgwt.client.ui.grid.renderer.IGridRenderContext;
import org.rcgwt.client.ui.grid.theme.IGridTheme;

/**
 * Context for the rendering process
 * 
 * @author Olivier Oeuillot
 * 
 */
public abstract class AbstractGridRenderContext implements IGridRenderContext {

    private final IGridModel gridModel;

    private final IGridTheme theme;

    private int[] columnModelIndexes;

    private int[] columnRenderedIndexes;

    private Map<String, Object> renderContextAttributes;

    private int startRowRenderedIndex;

    private int rendredRowCount;

    public AbstractGridRenderContext(IGridModel gridModel) {
        this.gridModel = gridModel;

        this.theme = gridModel.getGridWidget().getTheme();
    }

    @Override
    public void setRenderedRowIndex(int startRowRenderedIndex, int rowCount) {
        this.startRowRenderedIndex = startRowRenderedIndex;
        this.rendredRowCount = rowCount;
    }

    @Override
    public IGridModel getGridModel() {
        return gridModel;
    }

    @Override
    public IGridTheme getTheme() {
        return theme;
    }

    @Override
    public IntRangeList listAllVisibleRowModelIndexes() {

        int array[] = new int[256];
        int offset = 0;

        for (IViewModel viewModel : gridModel.listViewModels()) {

            IViewModelElements viewModelElements = viewModel
                    .getViewModelElements();

            IRowModel rowModels[] = viewModelElements
                    .listVisibleRowModels(viewModel);
            if (rowModels == null || rowModels.length == 0) {
                continue;
            }

            for (IRowModel rowModel : rowModels) {

                if (offset == array.length) {
                    int[] newArray = new int[array.length + 256];

                    System.arraycopy(array, 0, newArray, 0, array.length);

                    array = newArray;
                }

                array[offset++] = rowModel.getModelIndex();
            }
        }

        return new IntRangeList(array, 0, offset);
    }

    @Override
    public void setRenderContextAttribute(String attributeName, Object value) {
        if (renderContextAttributes == null) {
            renderContextAttributes = new HashMap<String, Object>();
        }

        renderContextAttributes.put(attributeName, value);
    }

    @Override
    public Object getRenderContextAttribute(String attributeName) {
        if (renderContextAttributes == null) {
            return null;
        }

        return renderContextAttributes.get(attributeName);
    }

    @Override
    public int[] getColumnModelIndexes() {
        if (columnModelIndexes != null) {
            return columnModelIndexes;
        }

        setupColumnIndexes();

        return columnModelIndexes;
    }

    @Override
    public int[] getColumnRenderedIndexes() {
        if (columnRenderedIndexes != null) {
            return columnRenderedIndexes;
        }

        setupColumnIndexes();

        return columnRenderedIndexes;
    }

    @SuppressWarnings("boxing")
    private void setupColumnIndexes() {
        IColumnProvider columnProvider = gridModel.getGridWidget()
                .getColumnProvider();

        int columnCount = columnProvider.getColumnCount();

        columnModelIndexes = new int[columnCount];
        columnRenderedIndexes = new int[columnCount];

        int renderedIndex = 0;
        for (Iterator<Integer> it = columnProvider.getColumnModelIndexes(); it
                .hasNext(); renderedIndex++) {

            Integer columnModelIndex = it.next();

            columnModelIndexes[columnModelIndex] = renderedIndex;
            columnRenderedIndexes[renderedIndex] = columnModelIndex;
        }
    }

}
